package com.lin.setting.setting.desensitization.serializer;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.lin.setting.setting.desensitization.Desensitization;
import com.lin.setting.setting.desensitization.FieldDesensitizationHelper;
import com.lin.setting.setting.desensitization.handler.DesensitizationHandler;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.util.Objects;

/**
 * @作者: 林江
 * @创建时间: 2024/5/3
 * @功能: 服务层 --> 视图层，对数据进行脱敏
 */
@Slf4j
public class DesensitizationSerializer extends JsonSerializer<String> implements ContextualSerializer {
    Class<? extends DesensitizationHandler> desensitizationHandler;

    @Override
    public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        log.info("脱敏序列化：{}", value);
        // 实现脱敏逻辑
        FieldDesensitizationHelper helper = new FieldDesensitizationHelper();
        DesensitizationHandler desensitization = helper.createDesensitizationHandler(desensitizationHandler);
        if (desensitization == null) {
            gen.writeString(value);
        } else {
            gen.writeString(desensitization.desensitization(value));
        }
    }

    /**
     * 这个方法只会执行一次，在于对某些字段进行序列化的时候，需要根据注解来判断是否需要脱敏。
     * 进行保存的类都会保存在jackson的上下文中，并且是互不相同的。
     *
     * @param serializerProvider | 序列化提供器
     * @param beanProperty       | 类属性的信息，有类型，名称，注解等
     * @return
     */
    @Override
    public JsonSerializer<?> createContextual(final SerializerProvider serializerProvider, final BeanProperty beanProperty) throws JsonMappingException {
        if (beanProperty != null) {
            if (Objects.equals(beanProperty.getType().getRawClass(), String.class)) {
                Desensitization sensitive = beanProperty.getAnnotation(Desensitization.class);
                if (sensitive == null) {
                    sensitive = beanProperty.getContextAnnotation(Desensitization.class);
                }
                if (sensitive != null) {
                    DesensitizationSerializer desensitizationSerializer = new DesensitizationSerializer();
                    desensitizationSerializer.setHandler(sensitive.handler());
                    return desensitizationSerializer;
                }
            }
            return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);
        }
        return serializerProvider.findNullValueSerializer(beanProperty);
    }

    private void setHandler(Class<? extends DesensitizationHandler> handler) {
        this.desensitizationHandler = handler;
    }

}
